﻿using Microsoft.EntityFrameworkCore;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;

namespace QuickCode.Domain.Entity
{
    /// <summary>
    /// 所有表的公共字段
    /// </summary>
    public abstract class DbBase
    {
        /// <summary>
        /// 主键Id
        /// </summary>
        [Key, MaxLength(63)]
        [Comment("主键Id")]
        public string Id { get; set; } = GuidHelper.GenerateGuid();

        /// <summary>
        /// 创建时间
        /// </summary>
        [Comment("创建时间")]
        public DateTime? CreateTime { get; set; } = DateTime.Now;

        /// <summary>
        /// 更新时间
        /// </summary>
        [Comment("更新时间")]
        public DateTime? UpdateTime { get; set; }

        /// <summary>
        /// 删除时间
        /// </summary>
        [Comment("删除时间")]
        public DateTime? DeleteTime { get; set; }

        /// <summary>
        /// 删除标志: 0正常,1删除
        /// </summary>
        [DefaultValue(0)]
        [Comment("删除标志: 0正常,1删除")]
        public int DeleteFlag { get; set; }

        /// <summary>
        /// 操作人id
        /// </summary>
        [MaxLength(63)]
        [Comment("操作人id")]
        public string? OperatorId { get; set; }

        /// <summary>
        /// 操作人姓名
        /// </summary>
        [MaxLength(63)]
        [Comment("操作人姓名")]
        public string? OperatorName { get; set; }

        /// <summary>
        /// 创建人id
        /// </summary>
        [MaxLength(63)]
        [Comment("创建人id")]
        public string? CreateId { get; set; }

        /// <summary>
        /// 创建人姓名
        /// </summary>
        [MaxLength(63)]
        [Comment("创建人姓名")]
        public string? CreateName { get; set; }
    }

    /// <summary>
    /// GUID帮助类
    /// </summary>
    public static class GuidHelper
    {
        /// <summary>
        /// 生成48位主键,时间戳+GUID
        /// </summary>
        /// <returns></returns>
        public static string GenerateKey()
        {
            return Guid.NewGuid().ToSequentialGuid().ToUpper();
        }

        /// <summary>
        /// 获取随机4位数字,可用于验证码
        /// </summary>
        /// <param name="number"></param>
        /// <returns></returns>
        public static string GenerateNumberKey(string number = "")
        {
            return number + (new Random().Next(1, 9999)).ToString().PadLeft(4, '0');
        }

        /// <summary>
        /// 生成GUID主键,前16位为时间戳,相比GenerateKey,速度快,节省空间,唯一性可能较差,但理论上够用
        /// </summary>
        /// <returns></returns>
        public static string GenerateGuid()
        {
            return Extention.SequenceGuid().ToString("N").ToUpper();
        }
    }
    public static partial class Extention
    {
        public static readonly RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create();

        /// <summary>
        /// 转为有序的GUID
        /// 注：长度为50字符
        /// </summary>
        /// <param name="guid">新的GUID</param>
        /// <returns></returns>
        public static string ToSequentialGuid(this Guid guid)
        {
            var timeStr = DateTime.Now.Ticks.ToString("x8");
            var newGuid = $"{timeStr.PadLeft(16, '0')}{guid.ToString("N")}";

            return newGuid;
        }

        /// <summary>
        /// 获取序列Guid
        /// </summary>
        /// <returns></returns>
        public static Guid SequenceGuid()
        {
            byte[] randomBytes = new byte[8];
            randomNumberGenerator.GetBytes(randomBytes);                            //创建8个字节的强随机数
            byte[] timestampBytes = BitConverter.GetBytes(DateTime.UtcNow.Ticks);   //获取当前long时间戳 千万分之一秒
            if (BitConverter.IsLittleEndian) Array.Reverse(timestampBytes);         //根据CPU架构(是否低位在前),判断是否需要翻转字节
            byte[] guidBytes = new byte[16];                                        //创建16个字节的空间(待转GUID)
            Buffer.BlockCopy(timestampBytes, 0, guidBytes, 0, 8);                   //拷贝时间戳
            Buffer.BlockCopy(randomBytes, 0, guidBytes, 8, 8);                      //拷贝强随机数
            return new Guid(guidBytes);
        }
    }
}